package com.wstuo.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.apache.log4j.Logger;


/**
 * 时间格式类
 * 
 * @author wstuo.com
 * 
 */
public class TimeUtils {
	private static final Logger LOGGER = Logger.getLogger(TimeUtils.class);
    public final static long DAY_MILLISECONDS = 86400000L;
    public final static long HOUR_MILLISECONDS = 3600000L;
    public final static long MINU_MILLISECONDS = 60000L;
    /**
     * yyyy-MM-dd HH:mm:ss,fff
     */
    public final static String DATETIME_MILLISECOND = "yyyy-MM-dd HH:mm:ss,fff";
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public final static String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * yyyy-MM-dd HH:mm
     */
    public final static String DATETIME_HOURS = "yyyy-MM-dd HH:mm";
    /**
     * yyyy-MM-dd
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * yyyy-MM
     */
    public final static String MONTH_PATTERN = "yyyy-MM";
    /**
     * yyyyMMddHHmmss
     */
    public final static String DATETIME_NOSPLIT = "yyyyMMddHHmmss";
    /**
     * yyyyMMddHHmm
     */
    public final static String DATETIME_HOURS_NOSPLIT = "yyyyMMddHHmm";

	/**
	 * 日期转换成字符串格式
	 * @param date
	 * @param format
	 * @return String
	 */
	public static String format(Date date, String format) {
		String str = "";
		if (date != null) {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			str = sdf.format(date);
		}
		return str;
	}
	/**
	 * 字符串换成日期
	 * 
	 * @param str
	 * @param format
	 * @return Date
	 */
	public static Date parse(String str, String format) {
		Date date = null;
		if (StringUtils.hasText(str)) {
			SimpleDateFormat sdf = new SimpleDateFormat(format);
			try {
				date = sdf.parse(str);
			} catch (ParseException e) {
				LOGGER.error(e);
			}
		}
		return date;
	}
	/**
	 * 判断日期为星期几
	 * 
	 * @param dt
	 * @return String
	 */
	public static String getWeekOfDate(Date dt) {
		String[] weekDays = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
		Calendar cal = Calendar.getInstance();
		cal.setTime(dt);
		int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0)
			w = 0;
		return weekDays[w];
	}
	/**
	 * 计算某天小时分钟数.
	 * 
	 * @param theDate
	 * @return Long
	 */
	public static Long getTimeOfDay(Date theDate) {
		Calendar theDateCl = new GregorianCalendar();
		theDateCl.setTime(theDate);
		return theDateCl.get(Calendar.HOUR_OF_DAY)
				* HOUR_MILLISECONDS
				+ theDateCl.get(Calendar.MINUTE)
				* MINU_MILLISECONDS;
	}

	/**
	 * 计算某天小时分钟秒数
	 * 
	 * @param theDate
	 * @return Long
	 */
	public static Long getTimeOfDays(Date theDate) {
		Calendar theDateCl = new GregorianCalendar();
		theDateCl.setTime(theDate);
		return theDateCl.get(Calendar.HOUR_OF_DAY)
				* HOUR_MILLISECONDS
				+ theDateCl.get(Calendar.MINUTE)
				* MINU_MILLISECONDS
				+ theDateCl.get(Calendar.SECOND) * 1000;
	}
	/**
	 * 判断日期是否一样.
	 * 
	 * @param date1
	 * @param dateLong
	 * @return Boolean
	 */
	public static Boolean equalTimeIsConsistent(Date date1, Long dateLong) {
		Calendar date1Cl = new GregorianCalendar();
		date1Cl.setTime(date1);

		Calendar dateLongCl = new GregorianCalendar();
		dateLongCl.setTimeInMillis(dateLong);

		// 判断日期是否一样
		if (date1Cl.get(Calendar.YEAR) == dateLongCl.get(Calendar.YEAR)
				&& date1Cl.get(Calendar.MONTH) == dateLongCl
						.get(Calendar.MONTH)
				&& date1Cl.get(Calendar.DATE) == dateLongCl.get(Calendar.DATE)) {
			return true;
		}
		return false;
	}
	/**
	 * 系统时间大于相加后的时间则返回true
	 * @param date
	 * @param months
	 * @return
	 */
	public static boolean beForNowMonthDate(Date date, Integer months){
		boolean result = false;
		if (date != null && months != null && months != 0) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			calendar.add(Calendar.MONTH, months);
			if (new Date().getTime() > calendar.getTime().getTime()) {
				result = true;
			}
		}
		return result;
	}
	/**
	 * 传入时间小于系统时间则返回true
	 * 
	 * @param date
	 * @return String
	 */
	public static boolean beForNowSystemDate(Date date) {
		boolean result = false;
		if (date != null && date.getTime() < new Date().getTime()) {
			result = true;
		}
		return result;
	}
	/**
	 * 根据开始和结束时间计算完整期天
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	public static Long periodDays(Date startTime, Date endTime) {
		Calendar start = new GregorianCalendar();
		start.setTime(startTime);
		Calendar end = new GregorianCalendar();
		end.setTime(endTime);
		long day = 86400000;// 一天的millis
		long mod = (end.getTimeInMillis() - start.getTimeInMillis()) / day;
		int n = start.get(Calendar.DAY_OF_WEEK);// 2009-1-1是周几
		// 周日到周六分别是1~7
		long cnt = mod / 7;// 几个整周
		cnt = cnt * 2;
		long yushu = mod % 7;
		if (n + yushu > 7)
			cnt = cnt + 2;// 过了周六
		if (n + yushu == 7)
			cnt++;// 正好是周六
		return mod - cnt + 1;

	}
	/**
	 * 时间周期验证
	 * @param str
	 * @return
	 */
	public static boolean weekend(String str) {
		if ( str == null || !str.matches( "[\\d]{1,5}-[\\d]{1,2}-[\\d]{1,2}" )) {
			return false;
		}
		Date date = TimeUtils.parse(str,TimeUtils.DATE_PATTERN);
		Calendar calendar = new GregorianCalendar();
		if(date!=null)
			calendar.setTime(date);
		if (calendar.get(Calendar.DAY_OF_WEEK) == 1|| calendar.get(Calendar.DAY_OF_WEEK) == 7)
			return true;
		else
			return false;
	}
	
	/**
     * 秒转换为天时分格式 （xxDDyyHHzzMM）
     * @param slaTime 秒
     * @return xxDDyyHHzzMM
     */
    public static String second2DHM(int slaTime) {
        int mi = 60;
        int hh = mi * 60;
        int dd = hh * 24;

        int day = slaTime / dd;
        int hour = (slaTime - day * dd) / hh;
        int minute = (slaTime - day * dd - hour * hh) / mi;

        return day + "DD" + hour + "HH" + minute + "MM";
    }
    /**
     * 根据传入时间和format格式时间
     * @param date
     * @param format
     * @return date
     */
    public static Date dateFormat(Date date, String format) {
        return parse(format(date,format),format);
    }
    /**
	 * 长整形转日期字符串
	 * 
	 * @param longTime
	 * @return Date
	 */
	public static Date formatLongTimeToDate(Long longTime) {
		Date result=null;
		if (longTime!=null){
			Calendar offTime = new GregorianCalendar();
			offTime.setTimeInMillis(longTime);
			result=offTime.getTime();
		}else{
			LOGGER.error("longTime is null error");
		}
		return result;
	}
	/**
	 * 根据timeMin（单位：分钟）来得到date偏差后的日期
	 * @param date 
	 * @param timeMin 
	 * @return
	 */
	public static Date getIntervalTime(Date date,int timeMin){
		if (date != null) {
			Calendar calendar = Calendar.getInstance();
			calendar.setTime(date);
			calendar.add(Calendar.MINUTE,timeMin);
			date = calendar.getTime();
		}
		return date;
	}
	
	/**
	 * 获取当前日期天最后的时间，如：2015-07-08 23:59:59
	 * @return
	 */
	public static Date getNowAllDay(){
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		Date date = calendar.getTime();
		return date;
	}
	/**
	 * 获取指定日期最早的时间，如：2015-07-08 00:00:00
	 * @return
	 */
	public static Date getAllDayFirst(Date date){
		Calendar calendar = Date2Calender(date);
		calendar.set(Calendar.HOUR_OF_DAY, 00);
		calendar.set(Calendar.MINUTE, 00);
		calendar.set(Calendar.SECOND, 00);
		return calendar.getTime();
	}
	/**
	 * 获取指定日期最晚的时间，如：2015-07-08 23:59:59
	 * @return
	 */
	public static Date getAllDayLast(Date date){
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}
	/**
	 * 比较两个时间，取出最小的
	 * @param dateA
	 * @param dateB
	 * @return
	 */
	public static Calendar getMinDate(Date dateA, Date dateB){
		Calendar date = Calendar.getInstance();
		if (dateA == null && dateB != null) {
			date.setTime(dateB);
		}else if (dateB == null && dateA != null) {
			date.setTime(dateA);
		}else if (dateA != null && dateB != null) {
			//当dateA小于dateB时，返回TRUE，当大于等于时，返回false；
			date.setTime( dateA.before( dateB ) ? dateA:dateB );
		}
		return date;
	}
	/**
	 * 比较两个时间，取出最大的
	 * @param dateA
	 * @param dateB
	 * @return
	 */
	public static Calendar getMaxDate(Date dateA, Date dateB){
		Calendar date = Calendar.getInstance();
		if (dateA == null && dateB != null) {
			date.setTime(dateB);
		}else if (dateB == null && dateA != null) {
			date.setTime(dateA);
		}else if (dateA != null && dateB != null) {
			//当dateA大于dateB时，返回TRUE，当小于等于时，返回false； 
			date.setTime( dateA.after( dateB ) ? dateA:dateB );
		}
		return date;
	}
	
	/**
	 * 合并日期，保留date的年月日，保留time的时分秒
	 * @param date
	 * @param time
	 * @return
	 */
	public static Date dateTransform(Date date,Date time){
		Calendar cd = Date2Calender(date);
		
		Calendar ct = Date2Calender(time);
		//保留date的年月日，保留time的时分秒
		ct.set(cd.get(Calendar.YEAR), cd.get(Calendar.MONTH), cd.get(Calendar.DAY_OF_MONTH));
		return ct.getTime();
	}
	/**
	 * 获取最大时间
	 * @return
	 */
	public static Date getMaxDate() {
		return new Date(4102415999000L);//2099/12/31 23:59:59
	}
	/**
	 * 获取最小时间
	 * @return
	 */
	public static Date getMinDate() {
		return new Date(0L);//1970/1/1 8:0:0
	}
	/**
	 * 得到当前日期weekCount周后的日期
	 * @param date
	 * @param day
	 * @return
	 */
	public static Date calcDateAfterDays(Date date ,int weekCount) {
		Calendar calendar = Date2Calender(date);
		calendar.add(Calendar.DAY_OF_YEAR, weekCount * 7);
		return calendar.getTime();
	}
	
	/**
	 * 得到当前日期有几个指定星期的日期
	 * 如计算当前日期，三个周六或者周日后的日期是哪一天；
	 * @param date 日期
	 * @param count  多少个
	 * @param weekIndex {@link Calendar.SATURDAY}
	 * @return
	 */
	public static Date calcDateWeekCount(Date date ,int count,int[] weekIndex) {
		Calendar calendar = Date2Calender(date);
		int priCount = count;
		if (weekIndex != null && weekIndex.length > 0) {
			while (priCount > 0) {
				for (int index : weekIndex) {
					if (index == calendar.get(Calendar.DAY_OF_WEEK)) {
						priCount --;
						break;
					}
				}
				calendar.add(Calendar.DAY_OF_YEAR, 1);
			}
			if (count > 0) {
				calendar.add(Calendar.DAY_OF_YEAR, -1);
			}
		}
		return calendar.getTime();
	}
	
	/**
	 * 获取一年最多有多少天
	 * @param date
	 * @return
	 */
	public static int calcYearDayCount(Date date) {
		Calendar c = Date2Calender(date);
		c.set(c.get(Calendar.YEAR),11,31);
		return c.get(Calendar.DAY_OF_YEAR);
	}
	
	/**
	 * 计算endDate 离 以startDate年的第一天 包含多少天；
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static int calcDateDayCount(Date startDate,Date endDate) {
		Calendar start = Date2Calender(startDate);
		Calendar end = Date2Calender(endDate);
		return calcDateDayCount(start, end);
	}

	/**
	 * 计算end 离 以start年的第一天 包含多少天；
	 * @param start
	 * @param end
	 * @return
	 */
	public static int calcDateDayCount(Calendar start,Calendar end) {
		Calendar startDate = Calendar.getInstance();
		startDate.set(start.get(Calendar.YEAR),11,31);
		int count = end.get(Calendar.DAY_OF_YEAR);
		int yearCount = end.get(Calendar.YEAR) - startDate.get(Calendar.YEAR);
		if (yearCount > 0) {
			for (int i = 0; i < yearCount; i++) {
				count += startDate.get(Calendar.DAY_OF_YEAR);
				startDate.add(Calendar.YEAR, 1);
			}
		}
		return count;
	}
	/**
	 * 获取指定日期的该月份最开始那天
	 * @param date
	 * @return
	 */
	public static Date getMonthFirstDay(Date date) {
		Calendar calendar = Date2Calender(date);
		calendar.set(calendar.get(Calendar.YEAR), 
				calendar.get(Calendar.MONTH), 1, 0, 0, 0);
		return calendar.getTime();
	}
	/**
	 * 获取指定日期的该月份最后那天
	 * @param date
	 * @return
	 */
	public static Date getMonthLastDay(Date date) {
		Calendar calendar = Date2Calender(date);
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 
				calendar.getActualMaximum(Calendar.DAY_OF_MONTH), 23, 59, 59);
		return calendar.getTime();
	}
	/**
	 * 日期转Calendar
	 * @param date
	 * @return
	 */
	private static Calendar Date2Calender(Date date){
		Calendar calendar = Calendar.getInstance();
		if (date != null) {
			calendar.setTime(date);
		}
		return calendar;
	}
	
	public static void date2String(Date date) {
		if (date == null) {
			LOGGER.error("date is null");
		}else{
			LOGGER.error( TimeUtils.format(date,DATETIME_PATTERN ) );
		}
	}
}
